﻿using ERP.ERPSystem.ProductionSystem.Dto;
using ERP.Team.ProductionSystem;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

namespace ERP.ERPSystem.ProductionSystem
{
    /// <summary>
    /// 工艺路线应用服务类，负责处理工艺路线相关的业务逻辑。
    /// 继承自 ApplicationService，是ABP框架的应用服务基类。
    /// 实现了 IWorkmanshipService 接口中定义的所有契约。
    /// </summary>
    public class WorkmanshipService : ApplicationService, IWorkmanshipService
    {
        // 依赖注入 ABP 框架的通用仓储，用于操作 Workmanship 实体
        private readonly IRepository<Workmanship, int> _workmanshipRepository;
        /// <summary>
        /// 构造函数，通过依赖注入获取工艺路线的仓储实例。
        /// </summary>
        /// <param name="workmanshipRepository">由DI容器提供的工艺路线仓储</param>
        public WorkmanshipService(IRepository<Workmanship, int> workmanshipRepository)
        {
            _workmanshipRepository = workmanshipRepository;
        }

        /// <summary>
        /// 创建一个新的工艺路线。
        /// </summary>
        /// <param name="input">创建工艺路线所需的数据传输对象（DTO）。</param>
        /// <returns>创建成功后的工艺路线DTO。</returns>
        public async Task<WorkmanshipDTO> CreateAsync(CreateUpdateWorkmanshipDto input)
        {
            // 使用 AutoMapper 将输入的 DTO 映射到 Workmanship 实体
            var workmanship = ObjectMapper.Map<CreateUpdateWorkmanshipDto, Workmanship>(input);

            // 如果前端勾选了 "自动生成编号"
            if (input.AutoGenerateCode)
            {
                // 定义并执行一个简单的自动生成规则，例如："WM" + 当前精确到毫秒的时间戳
                workmanship.WorkmanshipCode = "WM" + DateTime.Now.ToString("yyyyMMddHHmmssfff");
            }
            
            // 将新实体异步插入到数据库
            var result = await _workmanshipRepository.InsertAsync(workmanship);
            // 将插入后、携带新ID的实体映射回 DTO 并返回
            return ObjectMapper.Map<Workmanship, WorkmanshipDTO>(result);
        }

        /// <summary>
        /// 根据ID删除一个工艺路线。
        /// </summary>
        /// <param name="id">要删除的工艺路线ID。</param>
        public async Task DeleteAsync(int id)
        {
            await _workmanshipRepository.DeleteAsync(id);
        }

        /// <summary>
        /// 批量删除工艺路线。
        /// </summary>
        /// <param name="ids">要删除的工艺路线ID集合。</param>
        public async Task DeleteManyAsync(IEnumerable<int> ids)
        {
            await _workmanshipRepository.DeleteManyAsync(ids);
        }

        /// <summary>
        /// 根据ID获取单个工艺路线信息。
        /// </summary>
        /// <param name="id">要查询的工艺路线ID。</param>
        /// <returns>工艺路线DTO。</returns>
        public async Task<WorkmanshipDTO> GetAsync(int id)
        {
            var workmanship = await _workmanshipRepository.GetAsync(id);
            return ObjectMapper.Map<Workmanship, WorkmanshipDTO>(workmanship);
        }

        /// <summary>
        /// 获取分页的工艺路线列表，包含查询、排序和分页逻辑。
        /// </summary>
        /// <param name="input">查询条件，包含分页、排序和过滤信息。</param>
        /// <returns>分页的工艺路线列表。</returns>
        public async Task<PagedResultDto<WorkmanshipDTO>> GetListAsync(GetWorkmanshipInputDto input)
        {
            // 1. 从仓储获取 IQueryable<Workmanship>，这允许我们构建动态查询
            var queryable = await _workmanshipRepository.GetQueryableAsync();

            // 2. 应用动态查询条件
            var query = queryable
                // 当 WorkmanshipCode 不为空时，添加编号包含查询
                .WhereIf(!string.IsNullOrWhiteSpace(input.WorkmanshipCode), x => x.WorkmanshipCode.Contains(input.WorkmanshipCode))
                // 当 WorkmanshipName 不为空时，添加名称包含查询
                .WhereIf(!string.IsNullOrWhiteSpace(input.WorkmanshipName), x => x.WorkmanshipName.Contains(input.WorkmanshipName))
                // 当 IsNo 有值时，添加是否启用状态查询
                .WhereIf(input.IsNo.HasValue, x => x.IsNo == input.IsNo);

            // 3. [关键] 修正分页参数：
            // Layui 前端组件传来的 SkipCount 实际上是 1-based 的页码(page index)。
            // 在这里我们需要将它转换为数据库查询所需的 0-based 的要跳过的数据量(skip count)。
            var pageIndex = input.SkipCount;
            var skipCount = (pageIndex - 1) * input.MaxResultCount;
            if (skipCount < 0)
            {
                skipCount = 0; // 保证 skipCount 不为负数
            }

            // 4. 设置默认排序
            // 如果客户端没有指定排序字段，我们在此设置一个默认排序，以确保分页结果的稳定性。
            var sorting = input.Sorting;
            if (string.IsNullOrWhiteSpace(sorting))
            {
                sorting = "Id desc"; // 默认按ID倒序，即最新的记录显示在最前面
            }

            // 5. 获取应用筛选条件后的总记录数
            var totalCount = await AsyncExecuter.CountAsync(query);

            // 6. 应用排序和分页，从数据库查询数据
            // 为避免便捷扩展方法(.PageBy)的潜在问题，此处手动实现排序和分页逻辑
            var items = await AsyncExecuter.ToListAsync(
                query
                    .OrderBy(sorting)      // 应用排序
                    .Skip(skipCount)       // 跳过指定数量的记录
                    .Take(input.MaxResultCount)  // 获取当前页的记录
            );

            // 7. 将查询结果（实体列表）映射为 DTO 列表
            var dtoList = ObjectMapper.Map<List<Workmanship>, List<WorkmanshipDTO>>(items);

            // 8. 返回标准的分页结果对象
            return new PagedResultDto<WorkmanshipDTO>(totalCount, dtoList);
        }

        /// <summary>
        /// 更新一个已存在的工艺路线。
        /// </summary>
        /// <param name="id">要更新的工艺路线ID。</param>
        /// <param name="input">更新所需的数据传输对象（DTO）。</param>
        /// <returns>更新成功后的工艺路线DTO。</returns>
        public async Task<WorkmanshipDTO> UpdateAsync(int id, CreateUpdateWorkmanshipDto input)
        {
            // 1. 异步从数据库获取需要更新的实体
            var workmanship = await _workmanshipRepository.GetAsync(id);
            // 2. 使用 AutoMapper 将输入 DTO 的值更新到从数据库取出的实体上
            ObjectMapper.Map(input, workmanship);
            // 3. 将更新后的实体异步保存到数据库
            var result = await _workmanshipRepository.UpdateAsync(workmanship);
            // 4. 将更新后的实体映射回 DTO 并返回给客户端
            return ObjectMapper.Map<Workmanship, WorkmanshipDTO>(result);
        }
    }
}
